// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// h [author] rhyme_lph
// y [email]  rhymelph@gmail.com
// f [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/company_entity.dart';
import 'package:finance_app/src/entities/company_financial_year_entity.dart';
import 'package:finance_app/src/entities/current_subscription_entity.dart';
import 'package:finance_app/src/entities/role_permission_entity.dart';
import 'package:finance_app/src/entities/setting_app_entity.dart';
import 'package:finance_app/src/entities/setting_info_entity.dart';
import 'package:finance_app/src/entities/user_profile_entity.dart';
import 'package:finance_app/src/http_service/http_company_service.dart';
import 'package:finance_app/src/http_service/http_permission_service.dart';
import 'package:finance_app/src/http_service/http_setting_service.dart';
import 'package:finance_app/src/http_service/http_subscription_service.dart';
import 'package:finance_app/src/http_service/http_user_service.dart';
import 'package:finance_app/src/mixin/chat_room_action_mixin.dart';
import 'package:finance_app/src/mixin/scroll_to_hide_mixin.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/widgets/bottom_sheet/companies_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';

import 'dashboard/dashboard_drawer_provider.dart';
import 'dashboard/dashboard_view_provider.dart';
import 'hr_payroll/hr_and_payroll_provider.dart';

class DashboardProvider extends BaseProvider<RolePermissionEntity>
    with ScrollToHideMixin, ChatroomActionMixin {
  List<CompanyEntity> companies;

  GlobalKey assistantKey = GlobalKey();
  GlobalKey drawerKey = GlobalKey();

  @override
  Future get dataFuture => HttpPermissionService.getMyPermission();

  @override
  void initState() {
    super.initState();
    Config.dashboardProvider = this;
    _initData();
    if (!Config.eventBus.streamController.hasListener) {
      Config.eventBus.on<OSNotification>().listen((event) {
        onActionTo("push_notification", null, event.additionalData);
      });
    }

    if (Config.notificationToBeFired != null) {
      Config.eventBus.fire(Config.notificationToBeFired);
      Config.notificationToBeFired = null;
    }
  }

  Future<void> _initData() async {
    await _loadSettingApp();
    await _loadUserInfo();
    await loadAvailableCompany();
    await _loadCompanySubscription();
    await _loadSettingInfo();
    await getFinancialYears();
    await Config.initLoginValue();
    await Config.initNoLoginValue();
  }

  @override
  List<BaseProvider> registerChildProviders() {
    return [
      DashboardViewProvider(),
      HrAndPayrollProvider(),
      DashboardDrawerProvider(),
    ];
  }

  Future<void> _loadSettingInfo() async {
    await post(HttpSettingService.getSettingInfo(), onSuccess: (result) async {
      RProvider.myProvider.globalMap[ConfigKey.settingInfo] =
          BaseConfig.entityBase.formJson<SettingInfoEntity>(
              result.data[BaseConfig.presenterBase.dataKey]);
      await RProvider.myProvider.updateGlobalMap();
    });
  }

  Future<void> _loadSettingApp() async {
    if (Config.settingApp == null)
      await post(HttpSettingService.getSettingApp(), onSuccess: (result) async {
        RProvider.myProvider.globalMap[ConfigKey.settingApp] =
            BaseConfig.entityBase.formJson<SettingAppEntity>(
                result.data[BaseConfig.presenterBase.dataKey]);
        await RProvider.myProvider.updateGlobalMap();
      });
  }

  Future<void> _loadUserInfo() async {
    await post(HttpUserService.getMyProfile(), onSuccess: (result) async {
      RProvider.myProvider.globalMap[ConfigKey.userProfile] =
          BaseConfig.entityBase.formJson<UserProfileEntity>(
              result.data[BaseConfig.presenterBase.dataKey]);
      await RProvider.myProvider.updateGlobalMap();
    });
  }

  Future<void> loadAvailableCompany() async {
    await post(HttpCompanyService.companyList(), onSuccess: (result) async {
      companies = getEntityFromResult<List<CompanyEntity>>(result);
      CompanyEntity entity;
      for (final item in companies) {
        if (item.id.toString() == Config.userProfile.defaultCompanyId) {
          entity = item;
          break;
        }
      }
      RProvider.myProvider.globalMap[ConfigKey.currentCompany] = entity;
      await RProvider.myProvider.updateGlobalMap();
      update();
    });
    if (companies == null) {
      companies = [];
    }
  }

  void onChangeCompany() {
    obtainContext?.call((context) {
      showCompanyBottomSheet(context,
          companyId: Config.userProfile.defaultCompanyId,
          companies: companies,
          onEditCompany: _onNavEditCompany,
          onCreateCompany: _onNavCreateCompany,
          onChangeCompany: _onChangeCompany,
          onInviteTeamMembers: _onNavInviteTeamMembers);
    });
  }

  void _onNavCreateCompany() {
    Routes.navigateTo(RouterGenProviders.createBusinessProfilePage,
        replace: true);
  }

  void _onChangeCompany(CompanyEntity value) async {
    obtainContext?.call(Navigator.pop);
    RProvider.myProvider.globalMap[ConfigKey.currentCompany] = value;
    Config.userProfile.defaultCompanyId = value.id.toString();
    _loadCompanySubscription();
    _loadUserInfo();
    _loadSettingInfo();
    getFinancialYears();
    await RProvider.myProvider.updateGlobalMap();
    onTry();
  }

  void _onNavEditCompany(CompanyEntity value) {
    Routes.navigateTo(RouterGenProviders.companyProfilePage,
        params: {'data': value}, replace: true);
  }

  void onNavSub() {
    Routes.navigateTo(RouterGenProviders.subscriptionPage);
  }

  void _onNavInviteTeamMembers(CompanyEntity value) {
    Routes.navigateTo(RouterGenProviders.inviteTeamMembersPage);
  }

  Future<void> _loadCompanySubscription() async {
    await post(HttpSubscriptionService.getCompaniesSubscription(),
        onSuccess: (result) async {
      CurrentSubscriptionEntity entity =
          getEntityFromResult<CurrentSubscriptionEntity>(result);
      RProvider.myProvider.globalMap[ConfigKey.currentSubscription] = entity;
      await RProvider.myProvider.updateGlobalMap();
    });
  }

  Future<void> getFinancialYears() async {
    await post(HttpCompanyService.getFinancialYears(),
        autoHandler: AutoHandler.Toast, onSuccess: (result) async {
      RProvider.myProvider.globalMap[ConfigKey.currentFYs] =
          getEntityFromResult<List<CompanyFinancialYearEntity>>(result);
      await RProvider.myProvider.updateGlobalMap();
      update();
    });
  }

  void onRefreshDashboard(
      {bool refreshTransaction = true, bool refreshOverview = true}) {
    getChildProvider<DashboardViewProvider>().onRefreshDashboard(
        refreshTransaction: refreshTransaction,
        refreshOverview: refreshOverview);
  }

  @override
  FutureOr<RolePermissionEntity> transformData(
      RolePermissionEntity d, bool isCache) async {
    RProvider.myProvider.globalMap[ConfigKey.rolePermission] = d;
    await RProvider.myProvider.updateGlobalMap();
    return super.transformData(d, isCache);
  }
}
